import socket
import os
import time
from threading import Thread

class TunnelServer(Thread):
    def __init__(self):
        HOST = '0.0.0.0'  # Symbolic name meaning all available interfaces
        PORT = 50010           # Arbitrary non-privileged port
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s.bind((HOST, PORT))
        self.s.listen(20)
        self.s.settimeout(10)
        self.running = True
        super().__init__()

    def stop(self):
        self.running = False
	
    def run(self):
        thread_list = []
        while self.running:
            try:
                conn, addr = self.s.accept()
            except socket.timeout:
                print("accept time out!")
                continue
            print('Connected by', addr)
            t = Thread(name = str(addr), target=self.process_conn, args = (conn, addr))
            t.start()
            thread_list.append(t)
        for t in thread_list:
            t.join()

    def relocate(self, internal_addr):
        header = 'HTTP/1.1 302 Found\n'
        header += 'Server: pytinyserver\n'
        header += 'Location：http://'+internal_addr+'/\n'
        header += 'Content-type: text/html\n'
        content = header + "\n"
        content += '''<html><head><meta http-equiv="Refresh" content="0,URL=http://''' + internal_addr+ '''/"/></head><body>relocation to internal address</body></html>'''
        return content

    def process_conn(self, conn, addr):
        first_recv = True
        while True:
            try:
                data = conn.recv(100)
                if data == None or len(data) == 0:
                    break
            except Exception as e:
                print(e)
                break
            command = data[:10]
            if command == b'RegisterIp':
                # RegisterIp:listen_port
                self.internal_addr = str(addr[0])+":"+str(data.decode()[11:])
                send_byte = self.internal_addr.encode(encoding = 'ascii')
                print("internal:" + self.internal_addr + " size:" + str(len(send_byte)))
                conn.send(send_byte)
                first_recv = False
                continue
            elif command == b'GET / HTTP':
                if self.internal_addr == None:
                    location = 'www.baidu.com'
                else:
                    location = self.internal_addr
                http_response = self.relocate(location)
                print("response:" + http_response)
                conn.send(http_response.encode())
                first_recv = False
                continue
            else:
                print(data, addr)
                break
        conn.close()


if __name__ == '__main__':
    s = TunnelServer()
    print("start server")
    s.start()
    while True:
        b = input()
        print("input:"+b)
        if b == "q":
            break
    s.stop()
    s.join()
    print("stop server")
